﻿using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.OpenSsl;
using Org.BouncyCastle.Pkcs;
using Org.BouncyCastle.Security;
using System;
using System.IO;
using System.Security.Cryptography;

namespace Odyssey.BouncyCastle.RSAUtil.Implementations
{
    public class RSAPkcs1Formatter : RSAFormatter
    {
        protected sealed override RSAParameters CreateByPublicKey(string key)
        {
            key = KeyFormat(key, "PUBLIC KEY");

            var pr = new PemReader(new StringReader(key));
            var obj = pr.ReadObject();
            if (!(obj is RsaKeyParameters rsaKey))
            {
                throw new Exception("CreateByPublicKey faild!public key format is incorrect");
            }
            var rsaParameters = new RSAParameters();
            rsaParameters.Modulus = rsaKey.Modulus.ToByteArrayUnsigned();
            rsaParameters.Exponent = rsaKey.Exponent.ToByteArrayUnsigned();
            return rsaParameters;
        }

        protected sealed override RSAParameters CreateByPrivateKey(string key)
        {
            key = KeyFormat(key, "RSA PRIVATE KEY");
            var pemReader = new PemReader(new StringReader(key));
            if (!(pemReader.ReadObject() is AsymmetricCipherKeyPair asymmetricCipherKeyPair))
            {
                throw new Exception("CreateByPrivateKey falid!private key format is incorrect");
            }
            var rsaPrivateCrtKeyParameters =
               (RsaPrivateCrtKeyParameters)PrivateKeyFactory.CreateKey(
                   PrivateKeyInfoFactory.CreatePrivateKeyInfo(asymmetricCipherKeyPair.Private));
            var rsaParameters = new RSAParameters
            {
                Modulus = rsaPrivateCrtKeyParameters.Modulus.ToByteArrayUnsigned(),
                Exponent = rsaPrivateCrtKeyParameters.PublicExponent.ToByteArrayUnsigned(),
                P = rsaPrivateCrtKeyParameters.P.ToByteArrayUnsigned(),
                Q = rsaPrivateCrtKeyParameters.Q.ToByteArrayUnsigned(),
                DP = rsaPrivateCrtKeyParameters.DP.ToByteArrayUnsigned(),
                DQ = rsaPrivateCrtKeyParameters.DQ.ToByteArrayUnsigned(),
                InverseQ = rsaPrivateCrtKeyParameters.QInv.ToByteArrayUnsigned(),
                D = rsaPrivateCrtKeyParameters.Exponent.ToByteArrayUnsigned()
            };
            return rsaParameters;
        }
    }
}
